package io.openmessaging.utils;

import java.util.ArrayList;

/**
 * 使用 ThreadLocal 实现的累加器
 * 实测 40 线程下比 AtomicLong 快 10 倍，比 LongAdder 快 3 倍
 * 适用于多次累加，偶尔计算结果，对结果实时性要求不高的场景
 */
public class ThreadLocalLongAdder {
    private static final class LongWrapper {
        long value;
    }

    private ArrayList<LongWrapper> values = new ArrayList<>();
    private ThreadLocal<LongWrapper> threadLocalLong = new ThreadLocal<>();

    public void add(long x) {
        LongWrapper l = threadLocalLong.get();
        if (l == null) {
            synchronized (this) {
                if ((l = threadLocalLong.get()) == null) {
                    threadLocalLong.set(l = new LongWrapper());
                    values.add(l);
                }
            }
        }
        l.value += x;
    }

    public long longValue() {
        long sum = 0;
        for (int i = 0; i < values.size(); i++) {
            sum += values.get(i).value;
        }
        return sum;
    }

    private long mark;

    /**
     * @return 两次调用 increments 方法之间的增量
     */
    public long increments() {
        long longValue = longValue();
        try {
            return longValue - mark;
        } finally {
            mark = longValue;
        }
    }

    @Override
    public String toString() {
        return Long.toString(longValue());
    }
}
